package processes

import (
	"encoding/json"
	"errors"
	"fmt"
	"go-web-learning/src/02_message_system/02_message_system/chatroom/common/constants"
	"go-web-learning/src/02_message_system/02_message_system/chatroom/common/message"
	"go-web-learning/src/02_message_system/02_message_system/chatroom/common/netWork"
	"go-web-learning/src/02_message_system/02_message_system/chatroom/server/model"
)

type UserProcess struct {
	Conn     netWork.Conn
	userId   int
	userName string
}

func (u *UserProcess) ServerLoginProcess(data string) (err error) {
	// 1、先反序列化
	var loginReqMsg message.ClientMsgLogin
	err = json.Unmarshal([]byte(data), &loginReqMsg)
	if err != nil {
		fmt.Println("json unmarshal err:", err)
		return
	}
	var loginRespMsg message.SrvMsgLogin
	// 2、验证
	user, err := model.MyUserDao.Login(loginReqMsg.UserId, loginReqMsg.UserPwd)
	if err == nil {
		u.userId = user.UserId
		u.userName = user.UserName
		userManagerProcess.AddOnlineUser(u)

		loginRespMsg.Friends = u.getUserFriends()
		loginRespMsg.Code = constants.RESP_CODE_SUCCESS
		loginRespMsg.Msg = "登陆成功"
		loginRespMsg.User = *user
	} else if errors.Is(err, model.ERROR_USER_NOT_EXISTS) {
		loginRespMsg.Code = constants.RESP_CODE_LOGIN_FAIL_NOT_EXISTS
		loginRespMsg.Msg = err.Error()
	} else if errors.Is(err, model.ERROR_USER_PWD_ERR) {
		loginRespMsg.Code = constants.RESP_CODE_LOGIN_FAIL_PWD_ERR
		loginRespMsg.Msg = err.Error()
	} else {
		loginRespMsg.Code = constants.RESP_CODE_UNKNOWN_ERR
		loginRespMsg.Msg = "服务器内部错误"
	}
	respMsg := message.Message{}
	respMsg.SetType(constants.MSG_TYPE_LOGIN_RESP)
	err = respMsg.SetData(loginRespMsg)
	if err != nil {
		fmt.Println("resp set data err:", err)
		return err
	}
	// 发送
	u.Conn.SetMsg(respMsg)
	_, err = u.Conn.Send()
	return
}

func (u *UserProcess) ServerRegisterProcess(data string) (err error) {
	// 1、先反序列化
	var registerReqMsg message.ClientMsgRegister
	err = json.Unmarshal([]byte(data), &registerReqMsg)
	if err != nil {
		fmt.Println("json unmarshal err:", err)
		return
	}
	var registerRespMsg message.SrvMsgRegister
	// 2、注册
	user, err := model.MyUserDao.Register(registerReqMsg.UserId, registerReqMsg.UserPwd, registerReqMsg.UserName)
	if err == nil {
		userManagerProcess.ServerNotifyOthersNewFriend(user.UserId, user.UserName)
		registerRespMsg.Code = constants.RESP_CODE_SUCCESS
		registerRespMsg.Msg = "注册成功"
		registerRespMsg.User = *user
	} else if errors.Is(err, model.ERROR_USER_EXISTS) {
		registerRespMsg.Code = constants.RESP_CODE_REGISTER_FAIL_EXISTS
		registerRespMsg.Msg = err.Error()
	} else {
		registerRespMsg.Code = constants.RESP_CODE_UNKNOWN_ERR
		registerRespMsg.Msg = "服务器内部错误"
	}
	respMsg := message.Message{}
	respMsg.SetType(constants.MSG_TYPE_REGISTER_RESP)
	err = respMsg.SetData(registerRespMsg)
	if err != nil {
		fmt.Println("resp set data err:", err)
		return err
	}
	// 发送
	u.Conn.SetMsg(respMsg)
	_, err = u.Conn.Send()
	return
}

func (u *UserProcess) ServerNotifyOtherOnlineUsers(id int) {
	notifyMsg := message.Message{}
	notifyMsg.SetType(constants.MSG_TYPE_NOTIFY_USER_STATUS)
	srvMsg := message.SrvMsgNotifyUserStatus{
		UserId:     id,
		UserStatus: constants.USER_STATUS_ONLINE,
	}
	err := notifyMsg.SetData(srvMsg)
	if err != nil {
		return
	}
	u.Conn.SetMsg(notifyMsg)
	u.Conn.Send()
}

func (u *UserProcess) ServerNotifyOthersNewFriend(userId int, userName string) {
	notifyMsg := message.Message{}
	notifyMsg.SetType(constants.MSG_TYPE_NOTIFY_NEW_FRIEND)
	srvMsg := message.SrvMsgNotifyNewFriend{
		UserId:   userId,
		UserName: userName,
	}
	fmt.Println("11111")
	err := notifyMsg.SetData(srvMsg)
	if err != nil {
		return
	}
	u.Conn.SetMsg(notifyMsg)
	u.Conn.Send()
}

func (u *UserProcess) getUserFriends() (friends []message.User) {
	friends = make([]message.User, 0)
	userMap := model.MyUserDao.GetAllUsers()
	for id, name := range userMap {
		_, ok := userManagerProcess.onlineUsers[id]
		userStatus := constants.USER_STATUS_OFFLINE
		if ok {
			userStatus = constants.USER_STATUS_ONLINE
		}
		friends = append(friends, message.User{
			UserId:     id,
			UserName:   name,
			UserStatus: userStatus,
		})
	}
	return
}
